package com.hockeo.server.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;

import com.hockeo.server.data.DAO;
import com.hockeo.shared.domain.persistent.Image;
import com.hockeo.tinygds.TinyGDS;

/**
 * Simple servlet to process file upload requests.
 *
 * @version $Id$
 * @author jjanke
 */
public class FileUploadServlet extends HttpServlet
{
  private static final long   serialVersionUID     = 1L;
  private static final int    MAX_FILE_UPLOAD_SIZE = 32 * 1024;
  private static final String FILE_FIELD_PREFIX    = "file";
  private static final String ID_FIELD_PREFIX      = "id";

  @Override
  protected void doGet( HttpServletRequest rq, HttpServletResponse rp ) throws ServletException, IOException
  {
    rp.getWriter().write( "GET requests are not handled by " + getServletName() );
    rp.getWriter().close();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
   * javax.servlet.http.HttpServletResponse)
   */
  @Override
  protected void doPost( HttpServletRequest rq, HttpServletResponse rp ) throws ServletException, IOException
  {
    PrintWriter out = rp.getWriter();
    boolean fMultipart = ServletFileUpload.isMultipartContent( rq );

    rp.setContentType( "text/html" );

    if ( !fMultipart )
    {
      out.write( "Servlet " + getServletName() + " expected a multipart request." );
      out.close();
      return;
    }

    ServletFileUpload upload = new ServletFileUpload();
    upload.setSizeMax( MAX_FILE_UPLOAD_SIZE );

    try
    {
      FileItemIterator iter = upload.getItemIterator( rq );
      byte[] abBuffer = new byte[MAX_FILE_UPLOAD_SIZE];
      TinyGDS tgds = DAO.get().begin();
      String strId = null;
      int nItemIdx = 0;

      while ( iter.hasNext() )
      {
        FileItemStream filestream = iter.next();

        if ( filestream.isFormField() )
        {
          if ( filestream.getFieldName().startsWith( ID_FIELD_PREFIX ) )
          {
            strId = Streams.asString( filestream.openStream() );
            nItemIdx = Integer.parseInt( filestream.getFieldName().substring( ID_FIELD_PREFIX.length() ) );
          }
        }
        else
        {
          int nIdx = Integer.parseInt( filestream.getFieldName().substring( FILE_FIELD_PREFIX.length() ) );
          if ( strId == null || strId.length() == 0 || nItemIdx != nIdx )
          {
            out.write( "Found file without matching ID." );
            out.write( "<a href='/admin/upload.html' target='_self'>Try again</a>" );
            out.close();
            return;
          }

          InputStream in = filestream.openStream();
          int cRead = 0;
          int cTotalBytes = 0;
          while ( ( cRead = in.read( abBuffer, cTotalBytes, 1024 ) ) != -1 )
            cTotalBytes += cRead;

          in.close();

          Image img = new Image( strId, filestream.getContentType(), Arrays.copyOf( abBuffer, cTotalBytes ) );
          img.setDesc( filestream.getName() );
          tgds.put( img );

          strId = null;

          out.write( "Successfully uploaded file " + filestream.getName() );
          out.write( "<a href='/admin/upload.html' target='_self'>Upload another file</a>" );
          out.close();
        }
      }
    }
    catch ( FileUploadException ex )
    {
      out.write( "Error while uploading file: " + ex.getMessage() );
      out.write( "<a href='/admin/upload.html' target='_self'>Try again</a>" );
      out.close();
      return;
    }
  }
}
